package com.my12306.common.util;

import com.google.gson.Gson;
import com.my12306.common.constant.CommonConstants;
import com.sun.org.apache.xml.internal.security.utils.Base64;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.List;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Author:苏牧夕
 * @Date:2020/5/14 12:13
 * @Version 1.0
 */
@Component
public class CommentUtils {

    /**
     * 前端使用公密钥加密
     * 后端使用私密界面
     * RSA加密的私密钥
     */
    public static String private_key = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCd4Y4vmxPzAek+wRA7OxaRrEPS\n" +
            "iZvDnonLlKpnqb8wehc6X2RwDJ2eY1/cTwY77Kf1UELcpunVWK/yZza4PHnfT014zCs/zaMdHbmk\n" +
            "Km6fSaq7KbVuMRRUM0j+G9AZAE7VpHMBkSHZxtg/e52GyQ6L/ENFRgl5Zf30l+LtOfRm41wkJ4Ba\n" +
            "BcoXCPD+ygQz32uHdYagbzy/XpN/q2uWRBk3/ZFfr29oxnnY/XbxW+XcZYj8GBxFXW8qT+TG5k16\n" +
            "XQWYgImtt91lKVwgYt3qca2RTgph+DiAEJ8TyR23qFWvequoJN/SOvpDMM/6SF7pyC8ls26XeRz5\n" +
            "GcLS0Xary8ZVAgMBAAECggEAfZVG5nMygR/KCpLDeHndz+343OV8szPOY9NTYLXTUJotE8+BMue2\n" +
            "EKD3RWTOjqgGScmYBa/3XC75dZXIHvBr+Mc51paA6HWIA8b7PaxK5gVQ+yOIH6iGhRtuOkKhWuG1\n" +
            "05bFrD9nb7UNmiGYAfi3y33TfKzjKF+KjB6s8QoicBu1UP0ponEfcdj4q/rUzCRCZMZxnMmgZ/6E\n" +
            "EhWVpamNrJshjH4ZbOWAPRLYQBMwRQqCOxuGCg0X3wwrMdrKAkKiyKxr44YmOz/XqgNCVHAZDCH0\n" +
            "AW140d1LnorJeNFdQzIZWmeu4oxTxbUlVd0ixoX2soU/+5d+P7uXSUMBaNwLAQKBgQDWoID+8zyO\n" +
            "AfC91oDbR88vGTDLvi+V10uZxYJrw1bQ9Lx8zS1Xe1dGmi6pMx+LtUH/Uk4gzvAXJU/ks4lY1q1R\n" +
            "h70CxitsvX3Vn7Y97/Nf1Gc1XYzkS2O3rfKLKAMc9+qD+hF5/QpKZt2AppcAdhHf0ZPoIO3zT1u8\n" +
            "ey2pogep9QKBgQC8ULuebSCKGbVpYLQX9xuHPJ29w+nYOP/kTaceqt5WSYQ10fyl1br1W0uDCRbD\n" +
            "YWCIkKqiy5gvn2KyRNCgEf1UA30nBrtjdSq/+raF/fVTB9Xop1evPFDoUmOwbjfoIMj4YvH8+erB\n" +
            "bmrOzmvWtZeA20dH1h7DNTq8BKLVyjQO4QKBgB0jAwAZg1H//2+2LB4YvI63S8GNGyaraK8Cejco\n" +
            "+KM7Zk9HB23F585E5irALvsna0M/KC4aCcwKm7L/kJjH5BWaaNV0k7aabvfOS85SweZzjmNXROZF\n" +
            "Oc9YxQGROAL5wROTokW+TWRWXKG3e+5rGPgamoq71bHfRyPqUQOjZIj1AoGAXbplF55DItlW5MMg\n" +
            "AAma5v2xmWDohBkirBRGSMpM7W+b4VnJwRSXAEXXWLnuXYKbFH3EoFBrR9Cxw/7iQ7mQd/9gjEsa\n" +
            "e482nuT/ccOMFi6BNlIMH4kK0Acp3QeOxfeDb7V3si0Fvg7iFFrDa9NoO9doLAYTu59Dw48fKP+C\n" +
            "V6ECgYBUgXJGBwOKLWRthfaqTzqy8zR5EBv8iHYna0Cfxb6CgHn8YqeDXychBJnN9GfsTskfQ4dR\n" +
            "y0Es63QzX2nXcDTZ6baGCsnK0YP6DfO/RsfJsbgW3kE6FEaq2RHKRX2Jygi/IqdjbkNJOlOhdqLj\n" +
            "OUBuCk/3VX1VsqubK/I2WObL/g==";
    /**
     * RSA加密的公密钥
     */
    public static String public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAneGOL5sT8wHpPsEQOzsWkaxD0ombw56J\n" +
            "y5SqZ6m/MHoXOl9kcAydnmNf3E8GO+yn9VBC3Kbp1Viv8mc2uDx5309NeMwrP82jHR25pCpun0mq\n" +
            "uym1bjEUVDNI/hvQGQBO1aRzAZEh2cbYP3udhskOi/xDRUYJeWX99Jfi7Tn0ZuNcJCeAWgXKFwjw\n" +
            "/soEM99rh3WGoG88v16Tf6trlkQZN/2RX69vaMZ52P128Vvl3GWI/BgcRV1vKk/kxuZNel0FmICJ\n" +
            "rbfdZSlcIGLd6nGtkU4KYfg4gBCfE8kdt6hVr3qrqCTf0jr6QzDP+khe6cgvJbNul3kc+RnC0tF2\n" +
            "q8vGVQIDAQAB";
    private static Gson gson = new Gson();
    //加密算法
    private static String algorithm = "RSA";

    /**
     * 获取id地址
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = null;
        try {
            ipAddress = request.getHeader("x-forwarded-for");
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (ipAddress.equals("127.0.0.1")) {
                    // 根据网卡取本机配置的IP
                    try {
                        ipAddress = InetAddress.getLocalHost().getHostAddress();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                }
            }
            // 通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
            if (ipAddress != null) {
                if (ipAddress.contains(",")) {
                    return ipAddress.split(",")[0];
                } else {
                    return ipAddress;
                }
            } else {
                return "";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 生成随机数字6位
     *
     * @param code 生成的位数
     * @return
     */
    public static String getRandomCode(int code) {
        Random random = new Random();
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < code; i++) {
            result.append(random.nextInt(10));
        }
        return result.toString();
    }

    /**
     * @param html
     * @return
     */
    public static String getPartialText(String html) {
        String str = removeTag(html);
        if (str != null && str.length() > 1500) {
            return str.substring(0, 200);
        } else {
            if (str != null && str.length() > 160) {
                return str.substring(0, 150);
            } else {
                return str;
            }
        }
    }

    /**
     * 把html文本转换为纯文本
     */
    private static String removeTag(String htmlStr) {
        String regEx_script = "<script[^>]*?>[\\s\\S]*?<\\/script>"; // script
        String regEx_style = "<style[^>]*?>[\\s\\S]*?<\\/style>"; // style
        String regEx_html = "<[^>]+>"; // HTML tag
        String regEx_space = "\\s+|\t|\r|\n";// other characters

        Pattern p_script = Pattern.compile(regEx_script,
                Pattern.CASE_INSENSITIVE);
        Matcher m_script = p_script.matcher(htmlStr);
        htmlStr = m_script.replaceAll("");
        Pattern p_style = Pattern
                .compile(regEx_style, Pattern.CASE_INSENSITIVE);
        Matcher m_style = p_style.matcher(htmlStr);
        htmlStr = m_style.replaceAll("");
        Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
        Matcher m_html = p_html.matcher(htmlStr);
        htmlStr = m_html.replaceAll("");
        Pattern p_space = Pattern
                .compile(regEx_space, Pattern.CASE_INSENSITIVE);
        Matcher m_space = p_space.matcher(htmlStr);
        htmlStr = m_space.replaceAll(" ");
        return htmlStr;
    }

    /**
     * po实体转换为Vo实体
     *
     * @param source
     * @param targe
     * @param <T>
     * @return
     */
    public static <T> T getPoToVo(T source, T targe) {
        BeanUtils.copyProperties(source, targe);
        return targe;
    }

    /**
     * json字符串转换成对象
     *
     * @param json
     * @param classType
     * @param <T>
     * @return
     */
    public static <T> T jsonToObject(String json, Class<T> classType) {
        return gson.fromJson(json, classType);
    }

    public static void main(String[] args) throws Exception {
        String input = "ZCnlV+Uf+vsOQ8851cvn0ovw1W4dATYw1POG8tfdjherzLZ2YEG6Ot6fcJPWw1NgpgCrevtyZd9lxo4YGFE5xhxj2fRRdQieNW2z6FlwmhoA3r/c9Eqh/umKvFCmjqLXqFzY0tlDNbDorwx6MPHSMQXdC7PxhGZxqUiDNMp9fuDASxH7EXUVvOPTdEd5ETqrnSqrTRpegxx1s+xP7+TQLFyQpLEsio+YYRoSFyhS7zbcrE4TtCQBmMlklI0rIpQJwTuav+CX2SvNV8MyfoNFd6C9WW87z+8jYNLKYAWlfXjuEsIZ2HfwYKWvFiN35bJE5sgL8YbNMbZ/DTAp06Gwbg==";
//        String encryStr = encryptRSA(input);
//        System.out.println("加密后："+encryStr);
        String decryStr = decryptRSA(input);
        System.out.println("解密后：" + decryStr);
    }

    /**
     * 解密数据
     *
     * @param encrypted : 密文
     * @return : 原文
     * @throws Exception
     */
    public static String decryptRSA(String encrypted) throws Exception {
        // 创建加密对象
        Cipher cipher = Cipher.getInstance(algorithm);
        // 私钥解密
        cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(algorithm));
        // 使用base64进行转码
        byte[] decode = Base64.decode(encrypted);


        // 使用私钥进行解密
        byte[] bytes1 = cipher.doFinal(decode);
        return new String(bytes1);
    }

    /**
     * 使用密钥加密数据
     *
     * @param input : 原文
     * @return : 密文
     * @throws Exception
     */
    public static String encryptRSA(String input) throws Exception {
        // 创建加密对象
        Cipher cipher = Cipher.getInstance(algorithm);
        // 对加密进行初始化
        // 第一个参数：加密的模式
        // 第二个参数：你想使用公钥加密还是私钥加密
        // 我想使用私钥进行加密
        cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(algorithm));
        // 使用私钥进行加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        return Base64.encode(bytes);
    }

    /**
     * 解密数据
     *
     * @param algorithm   : 算法
     * @param encrypted   : 密文
     * @param privatecKey : 密钥
     * @return : 原文
     * @throws Exception
     */
    private static String decryptRSA(String algorithm, Key privatecKey, String encrypted) throws Exception {
        // 创建加密对象
        Cipher cipher = Cipher.getInstance(algorithm);
        // 私钥解密
        cipher.init(Cipher.DECRYPT_MODE, privatecKey);
        // 使用base64进行转码
        byte[] decode = Base64.decode(encrypted);


        // 使用私钥进行解密
        byte[] bytes1 = cipher.doFinal(decode);
        return new String(bytes1);
    }

    /**
     * 使用密钥加密数据
     *
     * @param algorithm : 算法
     * @param input     : 原文
     * @param publicKey : 密钥
     * @return : 密文
     * @throws Exception
     */
    private static String encryptRSA(String algorithm, Key publicKey, String input) throws Exception {
        // 创建加密对象
        Cipher cipher = Cipher.getInstance(algorithm);
        // 对加密进行初始化
        // 第一个参数：加密的模式
        // 第二个参数：你想使用公钥加密还是私钥加密
        // 我想使用私钥进行加密
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        // 使用私钥进行加密
        byte[] bytes = cipher.doFinal(input.getBytes());
        return Base64.encode(bytes);
    }

    /**
     * 保存公钥和私钥，把公钥和私钥保存到根目录
     *
     * @param algorithm 算法
     */
    private static void generateKey(String algorithm) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);
        // 生成密钥对
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 生成私钥
        PrivateKey privateKey = keyPair.getPrivate();
        // 生成公钥
        PublicKey publicKey = keyPair.getPublic();
        // 获取私钥的字节数组
        byte[] privateKeyEncoded = privateKey.getEncoded();
        // 获取公钥字节数组
        byte[] publicKeyEncoded = publicKey.getEncoded();
        // 使用base64进行编码
        private_key = Base64.encode(privateKeyEncoded);
        public_key = Base64.encode(publicKeyEncoded);
        System.out.println("========私钥===========");
        System.out.println(private_key);
        System.out.println("=========公钥=============");
        System.out.println(public_key);
    }

    /**
     * 读取公钥
     *
     * @param algorithm 算法
     * @return
     */
    private static PublicKey getPublicKey(String algorithm) throws Exception {
//        String publicKeyString = FileUtils.readFileToString(new File(publicPath), Charset.defaultCharset());
        // 创建key的工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 创建公钥规则
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decode(public_key));
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 读取私钥
     *
     * @param algorithm 算法
     * @return 返回私钥的key对象
     */
    private static PrivateKey getPrivateKey(String algorithm) throws Exception {
//        String privateKeyString = FileUtils.readFileToString(new File(priPath), Charset.defaultCharset());
        // 创建key的工厂
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        // 创建私钥key的规则
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(private_key));
        // 返回私钥对象
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 生成cookie
     *
     * @param cookieNmae
     * @param value
     * @param path       携带的路径
     * @param age        存活时间  单位: s
     * @return
     */
    public Cookie createCookie(String cookieNmae, String value, String path, int age) {
        Cookie cookie = new Cookie(cookieNmae, value);
        cookie.setPath(path);
        cookie.setMaxAge(age);
        cookie.setHttpOnly(false);
//        cookie.setDomain("");
        return cookie;
    }

    /**
     * 默认生成方法
     *
     * @param cookieNmae
     * @param value
     * @return
     */
    public Cookie createCookie(String cookieNmae, String value) {
        return createCookie(cookieNmae, value, CommonConstants.cookiePath, CommonConstants.maxAge);
    }

    /**
     * 根据cookie名字找cookie
     *
     * @param cookies
     * @param name
     * @return
     */
    public Cookie getCookie(List<Cookie> cookies, String name) {
        List<Cookie> first = cookies.stream().parallel().filter(cookie -> {
            return !cookie.getName().equals(name);
        }).distinct().collect(Collectors.toList());
        return first!=null?first.size()>0?first.get(0):null:null;
    }
}
